//
//  sierpinski_triangle_2d_recursion.cpp
//  GLDemo
//
//  Created by wneqi on 14-5-30.
//  Copyright (c) 2014年 xiewneqi. All rights reserved.
//

#include <stdio.h>
#include <cmath>
#include "sierpinski_triangle_2d_recursion.h"
#include "shader_initialize.h"

static int DivisionDepth = 5;
static int NumTriangles = pow (3, DivisionDepth);
Point2* points;


static GLuint vbos[1];
static GLuint vaos[1];

void makeup_triangle (Point2 a, Point2 b, Point2 c)
{
    static int i = 0;
    
    points[i] = a;
    ++ i;
    points[i] = b;
    ++ i;
    points[i] = c;
    ++ i;
}

void divide_triangle (Point2 a, Point2 b, Point2 c, int k)
{
    if (k > 0)
    {
        Point2 ab = (a + b) / 2.0;
        Point2 ac = (a + c) / 2.0;
        Point2 bc = (b + c) / 2.0;
        
        divide_triangle (a, ab, ac, k - 1);
        divide_triangle (c, ac, bc, k - 1);
        divide_triangle (b, bc, ab, k - 1);
    }
    else
    {
        makeup_triangle (a, b, c);
    }
}


void init_sierpinski_2d_recursion_main (int argc, char** argv)
{
    glutInit (&argc, argv);
    glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
    glutInitWindowSize (800, 600);
    glutInitWindowPosition (100, 100);
    glutCreateWindow ("Hello, sierpinski triangles");
    glutDisplayFunc (display_sierpinski_2d_recursion);
    init_sierpinski_2d_recursion_gl ();
    glutMainLoop ();
}


void init_sierpinski_2d_recursion_gl ()
{
    setup_triangles_data ();
    
    // 编译Shader
    GLuint shaderProgram = InitShader ("vbo_vao_vertex_shader.glsl", "vbo_vao_fragment_shader.glsl");
    glUseProgram (shaderProgram);
    GLuint posLoc = glGetAttribLocation (shaderProgram, "va_position");
    
    glGenBuffers (1, vbos);
    glGenVertexArrays (1, vaos);
    
    glBindBuffer (GL_ARRAY_BUFFER, vbos[0]);
    glBufferData (GL_ARRAY_BUFFER, sizeof (Point2) * NumTriangles * 3, points, GL_STATIC_DRAW);
    glBindVertexArray (vaos[0]);
    glEnableVertexAttribArray (posLoc);
    glBindBuffer (GL_ARRAY_BUFFER, vbos[0]);
    glVertexAttribPointer (posLoc, 2, GL_FLOAT, GL_FALSE, 0, 0);
    
    glClearColor (1, 1, 1, 1);
}

void setup_triangles_data ()
{
    points = new Point2[NumTriangles * 3];
    Point2 vertices[3] =
    {
        {-1, -1},
        {0, 1},
        {1, -1}
    };
    divide_triangle (vertices[0], vertices[1], vertices[2], DivisionDepth);}

void display_sierpinski_2d_recursion ()
{
    glClear (GL_COLOR_BUFFER_BIT);
    
    glBindVertexArray (vaos[0]);
    glDrawArrays (GL_TRIANGLES, 0, NumTriangles * 3);
    
    glFlush ();
}